package com.yuandian.business.monitor.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.api.business_monitor.po.AdvancedQuery;
import com.yuandian.api.business_monitor.po.QueryBusinessStepParams;
import com.yuandian.api.business_monitor.po.SearchParams;
import com.yuandian.api.business_monitor.vo.BusinessStepResVo;
import com.yuandian.api.business_monitor.vo.CodeDetailsVo;
import com.yuandian.api.management.entity.ConfGraph;
import com.yuandian.api.management.entity.ConfReturnCode;
import com.yuandian.api.management.feign.*;
import com.yuandian.api.management.vo.OptionVo;
import com.yuandian.bpm.common.core.constant.SecurityConstants;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.bpm.common.data.resolver.ParamResolver;
import com.yuandian.business.monitor.mapper.BusinessEndToEndDetailMapper;
import com.yuandian.business.monitor.service.IBusinessStepService;
import com.yuandian.constant.Constants;
import com.yuandian.enums.BaseTableName;
import com.yuandian.utils.*;
import com.yuandian.utils.poi.ExcelTitleUtils;
import com.yuandian.utils.poi.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 说明：业务概况service实现
 *
 * @Author yanjun
 * @Date 2020/10/26 16:14
 */
@Slf4j
@Service
public class BusinessStepServiceImpl implements IBusinessStepService {


//    @Autowired
//    private ISearchOptionService searchOptionService;


//    @Autowired
//    private IBusiDetailStatService busiDetailStatService;

    @Autowired
    private RemoteReturnCodeService remoteReturnCodeService;
	@Autowired
	private BusinessEndToEndDetailMapper businessEndToEndDetailMapper;
	@Autowired
	private RemoteBusinessHallService remoteBusinessHallService;
	@Autowired
	private RemoteEmployeeService remoteEmployeeService;
	@Autowired
	private RemoteMenuMappingService remoteMenuMappingService;
	@Autowired
	private RemoteOptionService remoteOptionService;
	@Autowired
	private RemoteStepService remoteStepService;
	@Autowired
	RemoteExclusiveIndicatorService remoteExclusiveIndicatorService;
	@Autowired
	private ExclusiveIndicator exclusiveIndicator;


	/**
	 * 响应状态 和 完整性 映射关系
	 */
	private static Map<String, String> dealStateMap = new HashMap<>();
	private static Map<String, String> isCompletionMap = new HashMap<>();


	@PostConstruct
	public void init() {

		dealStateMap.put("0", "失败");
		dealStateMap.put("1", "成功");

		isCompletionMap.put("0", "完整");
		isCompletionMap.put("1", "无响应");
		isCompletionMap.put("2", "请求不完整");
		isCompletionMap.put("3", "响应不完整");

	}

	/**
	 * 分页查询业务步骤数据
	 *
	 * @param params
	 * @return 通用返回对象
	 */
	@Override
	public PageDataInfo queryBusinessStepListPage(QueryBusinessStepParams params) {


		// 获取查询营业厅信息 Map<营业厅编码， 营业厅名称>
		Map<String, String> businessHallMap = new HashMap<>();
		// 获取操作员映射信息 Map<操作员ID, 操作员名称>
		Map<String, String> operatorMap = new HashMap<>();
		// 获取菜单映射信息 Map<菜单ID, 菜单名称>
		Map<String, String> menuMap = new HashMap<>();
		// 获取按钮映射信息 Map<按钮ID, 按钮名称>
		Map<String, OptionVo> buttonMap = new HashMap<>();
		// 获取步骤类型映射信息 Map<业务编码@步骤编码, 步骤类型>
		Map<String, String> stepTypeMap = new HashMap<>();
		// 获取 自定义返回码注释 回填到前端
		Map<String, String> codeMap = new HashMap<>();
		try {
			// 获取查询营业厅信息 Map<营业厅编码， 营业厅名称>
			SearchParams searchParams = new SearchParams();
			businessHallMap = getBusinessHallMap(searchParams);
			// 获取操作员映射信息 Map<操作员ID, 操作员名称>
			operatorMap = remoteEmployeeService.getOperatorMap(searchParams);
			// 获取菜单映射信息 Map<菜单ID, 菜单名称>
			menuMap = remoteMenuMappingService.getMenuMap(searchParams);
			// 获取按钮映射信息 Map<按钮ID, 按钮名称>
			List<OptionVo> optionVos = remoteOptionService.getButtonMap().getData();
			buttonMap = optionVos.stream().collect(Collectors.toMap(OptionVo::getValue, v -> v, (k1, k2) -> k1));
			// 获取步骤类型映射信息 Map<业务编码@步骤编码, 步骤类型>
			stepTypeMap = remoteStepService.queryStepTypeByBusinessCode().getData();
			// 获取 自定义返回码注释 回填到前端 Map<系统名称@返回码, 返回码注释>
			codeMap = getCodeExplain();
			// 获取办事处称呼 单位/营业厅
		}catch (Exception e){
			log.error("[监控查询-业务步骤列表]获取配置库参数错误，异常原因：{}", e.getMessage());
		}
		// 获取需要查询的表名, 字段名
		List<String> fields = getFields();


		// 设置查询条件进行分页查询并返回结果
		IPage page = new Page(params.getPageNum(), params.getPageSize());
		params.setDisplayFields(fields);
		paramsHandle(params);

		// 判断查询 定性详单表(dwd_business_step) 还是 未定性的详单表(dwd_business_step_unsure)
		params.setTableName(params.getIsUnsure() == 0 ? BaseTableName.BUSINESS_STEP.getName() : BaseTableName.BUSINESS_STEP_UNSURE.getName());

		List<BusinessStepResVo> businessStepResVos = businessEndToEndDetailMapper.queryBusinessStepListPage(page, params);

		long total = page.getTotal();

		// 执行数据封装,获取自定义字段
		List<Map<String, Object>> resList = new ArrayList<>();
		LinkedHashMap<String, Object> customMap = exclusiveIndicator.getCustomMap();
		// 处理结果
		String explain = "";
		for (BusinessStepResVo hit : businessStepResVos) {
			Map<String, Object> sourceMap = BeanUtil.beanToMap(hit);
			explain = codeMap.get(sourceMap.get("systemName") + "@" + sourceMap.get("customResCode"));
			explain = ObjectUtil.isEmpty(explain) ? "" : (" (" + explain + ")");

			sourceMap.put("customResCode", (sourceMap.get("customResCode") + explain));
			sourceMap.put("operatorName", ObjectUtil.isNotEmpty(sourceMap.get("operatorId") + "") ? (ObjectUtil.isNotEmpty(operatorMap.get(sourceMap.get("operatorId") + "")) ? operatorMap.get(sourceMap.get("operatorId") + "") : "-") : "-");
			sourceMap.put("menuName", ObjectUtil.isNotEmpty(sourceMap.get("menuId") + "") ? (ObjectUtil.isNotEmpty(menuMap.get(sourceMap.get("menuId") + "")) ? menuMap.get(sourceMap.get("menuId") + "") : "-") : "-");
//			sourceMap.put("buttonName", ObjectUtil.isNotEmpty(sourceMap.get("buttonId") + "") ? (ObjectUtil.isNotEmpty(buttonMap.get(sourceMap.get("buttonId") + "").getLabel()) ? buttonMap.get(sourceMap.get("buttonId") + "").getLabel() : "-") : "-");
			sourceMap.put("businessHallName", ObjectUtil.isNotEmpty(sourceMap.get("businessHall") + "") ? (ObjectUtil.isNotEmpty(businessHallMap.get(sourceMap.get("businessHall") + "")) ? businessHallMap.get(sourceMap.get("businessHall") + "") : "-") : "-");
			sourceMap.put("dealState", dealStateMap.get(sourceMap.get("dealState") + ""));
			sourceMap.put("isCompletion", isCompletionMap.get(sourceMap.get("isCompletion") + ""));
			sourceMap.put("stepType", stepTypeMap.get(sourceMap.get("businessCode") + "@" + sourceMap.get("stepCode")));
			sourceMap.put("id", String.valueOf(sourceMap.get("id")));

			// 对专属指标进行切割
			ExclusiveIndicator.getValueFromSpecifyParameters(sourceMap, customMap);
			resList.add(sourceMap);
		}

		// 返回结果集
		return new PageDataInfo(total, resList);
	}

	/**
	 * 查询营业厅信息并装换成 Map<营业厅编码， 营业厅名称>
	 *
	 * @param params 业务编码集合
	 * @return 搜索选项vo对象集合
	 */
	public Map<String, String> getBusinessHallMap(SearchParams params) {
		if (Objects.isNull(params)) {
			params = new SearchParams();
		}
		Map<String, String> map = new HashMap<>();
		List<Map<String, String>> list = remoteBusinessHallService.getBusinessHall(params).getData();
		if (ListUtils.isNotNull(list)) {
			for (Map<String, String> voMap : list) {
				if(ObjectUtil.isNotEmpty(voMap)){
					map.put(voMap.get("businessHallId"), voMap.get("label"));
				}
			}
		}
		return map;
	}

	/**
	 * 获取自定义返回码注释
	 *
	 * @return
	 */
	public Map<String, String> getCodeExplain() {

		Map<String, String> resMap = new HashMap<>();
		SearchParams params = new SearchParams();
		// 4:自定返回码类型  3: 数据库返回码 2：中间件返回码  1：web 返回码
		params.setTypeId(4);
		ConfReturnCode confReturnCode = new ConfReturnCode();
		confReturnCode.setTypeId(4);
		List<ConfReturnCode> list = remoteReturnCodeService.getCodeDetail(confReturnCode).getData();
		if (list != null && list.size() > 0) {
			resMap = list.stream().collect(Collectors.toMap(ConfReturnCode::getNameAndValue, ConfReturnCode::getExplain, (key1, key2) -> key2));
		}
		return resMap;
	}


	private QueryBusinessStepParams paramsHandle(QueryBusinessStepParams params) {


		// 营业厅名称或ID
		if (ObjectUtil.isNotEmpty(params.getBusinessHallIdOrName())) {
			if (params.getBusinessHallType() == 2) {
				// 根据前端传过来的单位名称列表获取对应的单位ID列表（因为 财厅项目 一个单位名称可能对应多个单位ID）
				List<String> businessHallIdList = getBusinessHallIdList(params);
				if (ListUtils.isNotNull(businessHallIdList)) {
					params.setBusinessHallIdList(businessHallIdList);
				}
			}
		}

		// 操作员名称或ID
		if (ObjectUtil.isNotEmpty(params.getOperatorIdOrName())) {
			if (params.getOperatorType() == 2) {
				// 根据前端传过来的操作员名称获取对应的操作员ID列表（因为 财厅项目 一个操作员名称可能对应多个操作员）
				List<String> operatorIdList = getOperatorIdList(params);
				params.setOperatorNameList(operatorIdList);
			}
		}
		//4.1 判断高级查询
		List<AdvancedQuery> advancedQuery = params.getAdvancedQuery();
		//将列名转换成下划线命名
		if (advancedQuery != null) {
			advancedQuery.forEach(e -> e.setColumn(StringUtils.toUnderlineName(e.getColumn())));
			params.setAdvancedQuery(advancedQuery);
		}
		return params;
	}

	private List<String> getOperatorIdList(QueryBusinessStepParams params) {

		List<String> operatorIdList = new ArrayList<>();
		if (StringUtils.isNotEmpty(params.getOperatorIdOrName())) {
			operatorIdList = remoteEmployeeService.getOperatorIdListByOperatorNameList(params.getOperatorIdOrName()).getData();
		}

		return operatorIdList;
	}

	/**
	 * 根据营业厅名称获取营业厅Id列表
	 *
	 * @param params
	 * @return
	 */
	private List<String> getBusinessHallIdList(QueryBusinessStepParams params) {
		List<String> businessHallIdList = new ArrayList<>();
		if (StringUtils.isNotEmpty(params.getBusinessHallIdOrName())) {
			try {
				businessHallIdList = remoteBusinessHallService.getBusinessHallIdListByHallNameList(params.getBusinessHallIdOrName()).getData();
			}catch (Exception e){
				log.error("调用配置系统查询营业厅id出错，错误原因：{}", e.getMessage());
				e.printStackTrace();
			}

		}
		return businessHallIdList;
	}

	/**
	 * 获取ES查询字段
	 *
	 * @return
	 */
	private List<String> getFields() {
		String[] fields = {
				"id", "business_detail_id", "resource_code", "system_id", "system_name",
				"business_code", "business_name", "step_code", "step_name", /*"stepType",*/
				"business_hall", "operator_id",/* "menuId",*/ /*"pageLabelId",*/ /*"pageSize",*/
				/*"buttonId",*/ "deal_state", "is_completion", "custom_res_code", "user_identify",
				"alarm_count", "start_time", "end_time", /*"startTimeUsec", "endTimeUsec",*/
				"deal_time", "request_bytes", "response_bytes", "exclusive_indicator", "is_alarm"
		};
		List<String> fieldList = Arrays.stream(fields).collect(Collectors.toList());
		// 把配置库所配置的自定义字段拼接在查询字段集合里
		LinkedHashMap<String, Object> customMap = exclusiveIndicator.getCustomMap();
		if (customMap != null && customMap.size() > 0) {
			for (Map.Entry<String, Object> entry : customMap.entrySet()) {
				String key = entry.getKey();
				fieldList.add(StringUtils.toUnderlineName(key));
			}
		}

		return fieldList;
	}


}
